﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="WebSiteFolder.cs" company="">
//   
// </copyright>
// <summary>
//   The web site folder.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Skymate.Core.IO.WebSite
{
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Linq;

    using Skymate.Core.IO.VirtualPath;

    /// <summary>
    /// The web site folder.
    /// </summary>
    public class WebSiteFolder : IWebSiteFolder
    {
        /// <summary>
        /// The _virtual path provider.
        /// </summary>
        private readonly IVirtualPathProvider _virtualPathProvider;

        /// <summary>
        /// Initializes a new instance of the <see cref="WebSiteFolder"/> class.
        /// </summary>
        /// <param name="virtualPathProvider">
        /// The virtual path provider.
        /// </param>
        public WebSiteFolder(IVirtualPathProvider virtualPathProvider)
        {
            this._virtualPathProvider = virtualPathProvider;
        }

        /// <summary>
        /// The list directories.
        /// </summary>
        /// <param name="virtualPath">
        /// The virtual path.
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable"/>.
        /// </returns>
        public IEnumerable<string> ListDirectories(string virtualPath)
        {
            if (!this._virtualPathProvider.DirectoryExists(virtualPath))
            {
                return Enumerable.Empty<string>();
            }

            return this._virtualPathProvider.ListDirectories(virtualPath);
        }

        /// <summary>
        /// The list files.
        /// </summary>
        /// <param name="virtualPath">
        /// The virtual path.
        /// </param>
        /// <param name="recursive">
        /// The recursive.
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable"/>.
        /// </returns>
        public IEnumerable<string> ListFiles(string virtualPath, bool recursive)
        {
            if (!recursive)
            {
                return this._virtualPathProvider.ListFiles(virtualPath);
            }

            return
                this._virtualPathProvider.ListFiles(virtualPath)
                    .Concat(this.ListFiles(this.ListDirectories(virtualPath)));
        }

        /// <summary>
        /// The file exists.
        /// </summary>
        /// <param name="virtualPath">
        /// The virtual path.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool FileExists(string virtualPath)
        {
            return this._virtualPathProvider.FileExists(virtualPath);
        }

        /// <summary>
        /// The read file.
        /// </summary>
        /// <param name="virtualPath">
        /// The virtual path.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
        public string ReadFile(string virtualPath)
        {
            if (!this._virtualPathProvider.FileExists(virtualPath))
            {
                return null;
            }

            using (var stream = this._virtualPathProvider.OpenFile(this.Normalize(virtualPath)))
            {
                using (var reader = new StreamReader(stream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        /// <summary>
        /// The copy file to.
        /// </summary>
        /// <param name="virtualPath">
        /// The virtual path.
        /// </param>
        /// <param name="destination">
        /// The destination.
        /// </param>
        public void CopyFileTo(string virtualPath, Stream destination)
        {
            using (var stream = this._virtualPathProvider.OpenFile(this.Normalize(virtualPath)))
            {
                stream.CopyTo(destination);
            }
        }

        /// <summary>
        /// The list files.
        /// </summary>
        /// <param name="directories">
        /// The directories.
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable"/>.
        /// </returns>
        private IEnumerable<string> ListFiles(IEnumerable<string> directories)
        {
            return directories.SelectMany(d => this.ListFiles(d, true));
        }

        /// <summary>
        /// The normalize.
        /// </summary>
        /// <param name="virtualPath">
        /// The virtual path.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private string Normalize(string virtualPath)
        {
            return this._virtualPathProvider.Normalize(virtualPath);
        }
    }
}